package com.longshanks.retrorally;

import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;

/**
 * An extension of GameImage, GameTile represents a tile used to build
 * a level in the game.
 * 
 * In addition to the GameImage properties, game tiles include a unique
 * key, tile type identifier and visibility setting. 
 * 
 * @author Dan Ruscoe (ruscoe.org)
 * @version 1.0
 */
public class GameTile extends GameImage
{
	public static final int TYPE_EMPTY = 0;
	public static final int TYPE_OBSTACLE = 1;
	public static final int TYPE_DANGEROUS = 2;
	public static final int TYPE_EXIT = 3;
	public static final int START = 4;
	
	private int mKey = 0;
	private int mType = TYPE_EMPTY;

	private boolean mVisible = true;
	
	private Rect mCollisionRect = null;
	
	public GameTile(Context context, Point point)
	{
		super(context);

		this.mX = point.x;
		this.mY = point.y;
	}
	
	public GameTile(Context context, int drawable, Point point)
	{
		super(context, drawable);
		
		this.mX = point.x;
		this.mY = point.y;
	}

	public boolean isDangerous()
	{
		return (this.mType == TYPE_DANGEROUS);
	}

	public boolean getCollision(float x, float y, int width, int height)
	{
		if (this.mCollisionRect == null)
		{
			this.mCollisionRect = new Rect((int)x, (int)y, ((int)x + width), ((int)y + height));
		}
		else
		{
			this.mCollisionRect.set((int)x, (int)y, ((int)x + width), ((int)y + height));
		}

		return (this.mCollisionRect.intersects((int)this.mX, (int)this.mY, ((int)this.mX + getWidth()), ((int)this.mY + getHeight())));
	}
	
	public boolean getCollision(int x, int y, int radius)
	{
		// clamp(value, min, max) - limits value to the range min..max

		// Find the closest point to the circle within the rectangle
		int closestX = clamp(x, (int) this.mX, (int) this.mX + getWidth());
		int closestY = clamp(y, (int)this.mY, (int) this.mY + getHeight());

		// Calculate the distance between the circle's center and this closest point
		int distanceX = x - closestX;
		int distanceY = y - closestY;

		// If the distance is less than the circle's radius, an intersection occurs
		int distanceSquared = (distanceX * distanceX) + (distanceY * distanceY);
		return distanceSquared < (radius * radius);
	}
	
	private int clamp(int value, int min, int max) {
		if(value < min) {
			return min;
		}
		else if(value > max) {
			return max;
			
		}
		else {
			return value;
		}
	}
	
	public boolean getCollision(GameUnit gameUnit)
	{
		return (gameUnit.getRect().intersects((int)this.mX, (int)this.mY, ((int)this.mX + mWidth), ((int)this.mY + mHeight)));
	}

	public int getKey()
	{
		return this.mKey;
	}
	
	public void setKey(int key)
	{
		this.mKey = key;
	}
	
	public int getType()
	{
		return this.mType;
	}
	
	public void setType(int type)
	{
		this.mType = type;
	}
	
	public boolean isVisible()
	{
		return this.mVisible;
	}

	public void setVisible(boolean visible)
	{
		this.mVisible = visible;
	}
	
	public boolean isCollisionTile()
	{
//		return ((this.mType != GameTile.TYPE_EMPTY && this.mType != GameTile.START) && this.mVisible);
		return ((this.mType != GameTile.TYPE_EMPTY) && this.mVisible);
	}

	public boolean isBlockerTile()
	{
		if (this.mType == GameTile.TYPE_EMPTY || this.mType == GameTile.START)
		{
			return false;
		}
		
		return true;
	}
}
